package com.tanhua.dubbo.server.api;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import com.tanhua.dubbo.server.enums.CommentType;
import com.tanhua.dubbo.server.enums.IdType;
import com.tanhua.dubbo.server.pojo.*;
import com.tanhua.dubbo.server.service.IdService;
import com.tanhua.dubbo.server.service.TimeLineService;
import com.tanhua.dubbo.server.vo.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author 王加鑫
 * @Date 2021/09/05 17:55
 * @Since JDK 1.8
 */
@Service(version = "1.0.0")
@Slf4j
public class QuanZiApiImpl implements QuanZiApi{

    //评论数据存储在Redis中key的前缀
    private static final String COMMENT_REDIS_KEY_PREFIX = "QUANZI_COMMENT_";

    //用户是否点赞的前缀
    private static final String COMMENT_USER_LIKE_REDIS_KEY_PREFIX = "USER_LIKE_";

    //用户是否喜欢的前缀
    private static final String COMMENT_USER_LOVE_REDIS_KEY_PREFIX = "USER_LOVE_";

    @Reference(version = "1.0.0")
    private MessagesApi messagesApi;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private IdService idService;

    @Autowired
    private TimeLineService timeLineService;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    /**
     * 查询好友状态
     * 每个用户都拥有自己的时间线表，时间线表(TimeLine)包含自己所有好友的userId和publishId(发布id)
     * 查询好友动态需要去时间线表查询出好友的publishId集合(为什么需要publishId而不根据userId查呢，因为Publish表中保存着多个用户的动态，即
     * userId会有重复，而publishId唯一！！！)
     * 发布表(Publish)包含了所有用户发布的动态，拥有publishId和userId
     * 然后去Publish表中根据publishIds查询出所有数据
     * @param userId 登陆者id
     * @param page
     * @param pageSize
     * @return
     */
    @Override
    public PageInfo<Publish> queryPublishList(Long userId, Integer page, Integer pageSize) {
        PageInfo<Publish> pageInfo = new PageInfo<>();
        pageInfo.setPageNum(page);
        pageInfo.setPageSize(pageSize);
        //查询好友动需要先去TimeLine时间线表中查询出所有好友的publishId
        Query query = new Query().with(Sort.by(Sort.Order.desc("date"))).with(PageRequest.of(page-1,pageSize));
        List<TimeLine> timeLineList = this.mongoTemplate.find(query, TimeLine.class, "quanzi_time_line_" + userId);
        if(CollUtil.isEmpty(timeLineList)){
            return pageInfo;
        }
        //遍历timeLineList获取所有发布id(publishIds)的集合
        List<Object> publishIds = CollUtil.getFieldValues(timeLineList, "publishId");
        if(CollUtil.isEmpty(publishIds)){
            return pageInfo;
        }
        //根据publishIds去Publish发布表中查询数据
        Query queryPublish = Query.query(Criteria.where("id").in(publishIds)).with(Sort.by(Sort.Order.desc("created")));
        List<Publish> publishList = this.mongoTemplate.find(queryPublish, Publish.class);
        if(CollUtil.isEmpty(publishList)){
            return pageInfo;
        }
        pageInfo.setRecords(publishList);
        return pageInfo;
    }

    /**
     * 查询publish表所有的数据，作测试用
     * @return
     */
    @Override
    public List<Publish> queryPublishList() {
        Query query = new Query().with(Sort.by(Sort.Order.asc("created")));
        List<Publish> publishList = this.mongoTemplate.find(query, Publish.class);
        return publishList;
    }

    /**
     * 根据userId查询这个用户的所有动态（给后台系统用）
     * @param userId
     * @param page
     * @param pageSize
     * @param sortOrder
     * @return
     */
    @Override
    public List<Publish> queryPublishList(Long userId, Integer page, Integer pageSize, String sortOrder) {
        Query query = null;
        if(sortOrder.equals("ascending")){
            query = new Query().with(Sort.by(Sort.Order.asc("created"))).with(PageRequest.of(page-1,pageSize));
        }else if(sortOrder.equals("descending")){
            query = new Query().with(Sort.by(Sort.Order.desc("created"))).with(PageRequest.of(page-1,pageSize));
        }
        //查询好友动需要先去TimeLine时间线表中查询出所有好友的publishId
        List<TimeLine> timeLineList = this.mongoTemplate.find(query, TimeLine.class, "quanzi_album_" + userId);
        if(CollUtil.isEmpty(timeLineList)){
            return ListUtil.empty();
        }
        //遍历timeLineList获取所有发布id(publishIds)的集合
        List<Object> publishIds = CollUtil.getFieldValues(timeLineList, "publishId");
        if(CollUtil.isEmpty(publishIds)){
            return ListUtil.empty();
        }
        //根据publishIds去Publish发布表中查询数据
        Query queryPublish = null;
        //根据publishIds去Publish发布表中查询数据
        if(sortOrder.equals("ascending")){
            queryPublish = Query.query(Criteria.where("id").in(publishIds)).with(Sort.by(Sort.Order.asc("created")));
        }else if(sortOrder.equals("descending")){
            queryPublish = Query.query(Criteria.where("id").in(publishIds)).with(Sort.by(Sort.Order.desc("created")));
        }
        List<Publish> publishList = this.mongoTemplate.find(queryPublish, Publish.class);
        if(CollUtil.isEmpty(publishList)){
            return ListUtil.empty();
        }
        return publishList;

    }

    /**
     * 根据Publish表_id的字段的集合查询publish表的数据 （给后台系统用）
     * @param publishIds
     * @param page
     * @param pageSize
     * @param sortOrder 分页条件
     * @return
     */
    public List<Publish> queryPublishList(List<String> publishIds, Integer page, Integer pageSize, String sortOrder) {
        List<ObjectId> publishIdList = new ArrayList<>();
        for (String id : publishIds) {
            //将String类型转化为ObjectId类型
            publishIdList.add(new ObjectId(id));
        }
        Query queryPublish = null;
        //根据publishIds去Publish发布表中查询数据
        if(sortOrder.equals("ascending")){
            queryPublish = Query.query(Criteria.where("id").in(publishIds)).with(Sort.by(Sort.Order.asc("created")));
        }else if(sortOrder.equals("descending")){
            queryPublish = Query.query(Criteria.where("id").in(publishIds)).with(Sort.by(Sort.Order.desc("created")));
        }
        List<Publish> publishList = this.mongoTemplate.find(queryPublish, Publish.class);
        if(CollUtil.isEmpty(publishList)){
            return ListUtil.empty();
        }
        return publishList;
    }

    /**
     * 用户发布动态，需要往三张表分别写入数据，分别是Publish,TimeLine,Album
     * 封装一份Publish表的数据往三张表中写，TimeLine表最为特殊，需要异步写入
     * @param publish
     * @return 发布成功返回动态id
     */
    @Override
    public String savePublish(Publish publish) {
        //根据Text和UserId来判断是否接收到用户输入的数据
        if(ObjectUtil.isAllEmpty(publish.getText(),publish.getUserId())){
            return null;
        }
        //这里需要写入用户在页面输入不到的数据，_id,pid,created
        //用户发布成功，开始往Publish表写入数据
        publish.setId(ObjectId.get());
        try {
            publish.setPid(idService.created(IdType.PUBLISH));
            //设置时间为当前时间戳
            publish.setCreated(System.currentTimeMillis());
            this.mongoTemplate.save(publish);

            /**
             * 将数据写入到album用户相册表中
             * 相册表是每个用户自己独有一份的
             * 这里根据后缀用户id来区分
             */
            Album album = new Album();
            album.setId(ObjectId.get());
            album.setPublishId(publish.getId());
            album.setCreated(System.currentTimeMillis());
            this.mongoTemplate.save(album,"quanzi_time_line_" + publish.getUserId());
            /**
             * 将数据写入到所有好友的时间线表中
             * 异步写入
             */
            this.timeLineService.saveTimeLine(publish.getId(),publish.getUserId());
            this.savePublishToMessages(publish);

        } catch (Exception e) {
            //TODO 需要做事务的回滚，Mongodb的单节点服务，不支持事务，对于回滚我们暂时不实现了
            log.error("发布动态失败~ publish = " + publish, e);
        }
        return publish.getId().toHexString();
    }


    /**
     * 查询推荐用户动态(从redis中取出推荐数据Publish表中的pid字段)
     * @param userId
     * @param page
     * @param pageSize
     * @return
     */
    @Override
    public PageInfo<Publish> queryRecommend(Long userId, Integer page, Integer pageSize) {
        PageInfo<Publish> pageInfo = new PageInfo<>();
        pageInfo.setPageSize(pageSize);
        pageInfo.setPageNum(page);

        //查询推荐结果数据
        String key = "QUANZI_PUBLISH_RECOMMEND_" + userId;
        String data = this.redisTemplate.opsForValue().get(key);
        if(StringUtils.isEmpty(data)){
            return pageInfo;
        }

        //查询到的pid进行分页处理
        String[] pids = StringUtils.split(data, ",");

        List<Long> pidList = new ArrayList<>();
        for (String pid : pids) {
            pidList.add(Long.valueOf(pid));
        }
        Query query = Query.query(Criteria.where("pid").in(pidList)).with(Sort.by(Sort.Order.desc("created"))).with(PageRequest.of(page-1,pageSize));
        List<Publish> publishList = this.mongoTemplate.find(query, Publish.class);
        if(CollUtil.isEmpty(publishList)){
            return pageInfo;
        }

        pageInfo.setRecords(publishList);

        return pageInfo;
    }

    /**
     * 根据动态id查询Publish表中数据
     * @param id 动态id(Publish表的_id字段？)
     * @return
     */
    @Override
    public Publish queryPublishById(String id) {
        return this.mongoTemplate.findById(new ObjectId(id),Publish.class);
    }

    /**
     * 点赞功能
     * mongodb数据库保存有该数据
     * redis缓存保存有该数据(缓存中能唯一保证点赞的是：publishId + CommentType枚举类型 + userId)
     * @param userId
     * @param id
     * @return
     */
    @Override
    public Boolean likeComment(Long userId, String id) {
        //判断该用户是否已经点赞，如果已经点赞就直接返回
        if(this.queryUserIsLike(userId,id)){
            return false;
        }

        //点赞的逻辑
        //保存Comment数据
        Boolean result = this.saveComment(userId, id, CommentType.LIKE, null);
        if(!result){
            //保存失败
            return false;
        }

        //修改redis中的点赞数以及是否点赞
        //修改点赞数
        String redisKey = COMMENT_REDIS_KEY_PREFIX + id;
        String hashKey = CommentType.LIKE.toString();
        this.redisTemplate.opsForHash().increment(redisKey, hashKey, 1);

        //用户是否点赞
        String userLikeHashKey = COMMENT_USER_LIKE_REDIS_KEY_PREFIX + userId;
        this.redisTemplate.opsForHash().put(redisKey, userLikeHashKey, "1");
        return true;
    }

    /**
     * 查询用户是否点赞该动态
     * true 点赞 false 没有点赞
     * @param userId 用户id
     * @param id 用户发布的id
     * @return
     */
    @Override
    public Boolean queryUserIsLike(Long userId, String id) {
        // 从redis中查询数据
        String redisKey = COMMENT_REDIS_KEY_PREFIX + id;
        String userHashKey = COMMENT_USER_LIKE_REDIS_KEY_PREFIX + userId;
        Object data = this.redisTemplate.opsForHash().get(redisKey, userHashKey);
        if(ObjectUtil.isNotEmpty(data)){
            //如果缓存不为空，判断data中的数据是否为1
            return StrUtil.equals(Convert.toStr(data),"1");
        }
        //查询Mongodb,确定是否已经点赞
        Query query = Query.query(Criteria.where("publishId").is(new ObjectId(id))
                .and("userId").is(userId)
                .and("commentType").is(CommentType.LIKE.getType()));
        long count = this.mongoTemplate.count(query, Comment.class);
        if(count == 0){
            return false;
        }
        //已经点赞，写入到redis中
        this.redisTemplate.opsForHash().put(redisKey, userHashKey,"1");
        return true;
    }



    /**
     * true:需要取消点赞
     * false:不需要取消点赞
     * 取消点赞
     * @param userId
     * @param id
     * @return
     */
    @Override
    public Boolean disLikeComment(Long userId, String id) {
        //判断用户是否点赞
        if(!this.queryUserIsLike(userId,id)){
            //用户没有点赞则不需要取消点赞
            return false;
        }
        //执行删除逻辑
        Boolean flag = this.removeComment(id,userId,CommentType.LIKE);
        if(!flag){
            return false;
        }

        //修改redis中的点赞数以及是否点赞
        //修改点赞数
        String redisKey = COMMENT_REDIS_KEY_PREFIX + id;
        String hashKey = CommentType.LIKE.toString();
        this.redisTemplate.opsForHash().increment(redisKey, hashKey, -1);

        //用户是否点赞
        String userHashKey = COMMENT_USER_LIKE_REDIS_KEY_PREFIX + userId;
        this.redisTemplate.opsForHash().delete(redisKey, userHashKey);
        return true;

    }

    /**
     * 查询点赞数量
     * @param
     * @param id
     * @return
     */
    @Override
    public Long queryLikeCount(String id) {
        //首先需要去redis缓存中查询数据
        String redisKey = COMMENT_REDIS_KEY_PREFIX + id;
        String hashKey = CommentType.LIKE.toString();
        Object data = this.redisTemplate.opsForHash().get(redisKey, hashKey);
        if(ObjectUtil.isNotEmpty(data)){
            //如果redis中有数据直接从缓存中取
            return Convert.toLong(data);
        }

        //如果缓存中没有数据就需要去mongodb数据库中查询数据
        Long likeCount = this.queryCommentCount(id, CommentType.LIKE);
        //保险起见，再将查询到的数据写入到redis缓存当中
        this.redisTemplate.opsForHash().put(redisKey,hashKey,Convert.toStr(likeCount));
        return likeCount;
    }

    /**
     * 新增一条Comment数据
     * @param userId
     * @param id
     * @param commentType
     * @param content
     * @return
     */
    private Boolean saveComment(Long userId, String id, CommentType commentType, String content) {

        Comment comment = new Comment();
        comment.setId(ObjectId.get());
        comment.setCreated(System.currentTimeMillis());
        comment.setPublishId(new ObjectId(id));
        comment.setCommentType(commentType.getType());
        comment.setContent(content);
        comment.setUserId(userId);  //评论人(当前用户)
        Query query = Query.query(Criteria.where("publishId").is(id));
        Publish publish = this.mongoTemplate.findOne(query, Publish.class);
        if(ObjectUtil.isNotEmpty(publish)){
            comment.setPublishUserId(publish.getUserId()); //发布动态的用户id
        }else {
            //这里的publishUserId就不是发布动态的用户了，是评论id
            Comment userComment = this.mongoTemplate.findOne(query, Comment.class);
            if(ObjectUtil.isNotEmpty(userComment)){
                comment.setPublishUserId(comment.getUserId()); //评论该条动态的用户id
            }else {
                //评论该条小视频的用户id
                Video video = this.mongoTemplate.findOne(query, Video.class);
                if(ObjectUtil.isNotEmpty(video)){
                    comment.setPublishUserId(video.getUserId());
                }
            }
        }
        return this.mongoTemplate.save(comment) != null;
    }

    /**
     * 根据publishId查询Comment对象
     * @param id
     * @return
     */
    private Comment queryCommentById(String id) {
        return this.mongoTemplate.findById(new ObjectId(id), Comment.class);
    }

    /**
     * publishId,userId,commentType精准定位到想要删除的评论(取消点赞，取消喜欢，删除评论等)
     * @param id
     * @param userId
     * @param commentType
     * @return
     */
    private Boolean removeComment(String id,Long userId,CommentType commentType) {
        Query query = Query.query(Criteria.where("publishId").is(new ObjectId(id)).and("userId").is(userId).and("commentType").is(commentType.getType()));
        return this.mongoTemplate.remove(query,Comment.class).getDeletedCount() > 0;
    }


    /**
     * 根据publishId，commentType(评论类型)查询评论数量
     * @param id
     * @param commentType
     * @return
     */
    private Long queryCommentCount(String id, CommentType commentType){
        Query query = Query.query(Criteria.where("publishId").is(new ObjectId(id)).and("commentType").is(commentType.getType()));
        return this.mongoTemplate.count(query,Comment.class);
    }

    /**
     * 喜欢(用户点击喜欢的那一个动作)
     * @param
     * @param id
     * @return
     */
    @Override
    public Boolean loveComment(Long userId, String id) {
        /**
         * 如何根据 userId和publishId实现喜欢的功能呢？
         */
        //首先判断一下客户是否已经喜欢
        if(this.queryUserIsLove(userId,id)){
            //如果用户已经喜欢了，就没必要走下面的逻辑
            return false;
        }

        //喜欢，点赞，评论都是新增一条comment表中数据
        Boolean result = this.saveComment(userId, id, CommentType.LOVE, null);
        if(!result){
            //新增失败，返回false
            return false;
        }

        //修改redis中的数据
        //修改喜欢数
        String publishKey = COMMENT_REDIS_KEY_PREFIX + id;
        String hashKey = CommentType.LOVE.toString();
        // 将数量+1操作
        this.redisTemplate.opsForHash().increment(publishKey,hashKey,1);

        //用户是否点赞的标识 "1"说明处于点赞状态，没有则代表不处于点赞状态
        String userLoveHashKey = COMMENT_USER_LOVE_REDIS_KEY_PREFIX + userId;
        this.redisTemplate.opsForHash().put(publishKey,userLoveHashKey,"1");
        return true;
    }

    /**
     * 取消喜欢(用户取消喜欢的那个动作)
     * @param
     * @param id
     * @return
     */
    @Override
    public Boolean disLoveComment(Long userId, String id) {
        if(!this.queryUserIsLove(userId,id)){
            return false;
        }
        /*
        如何取消喜欢，comment表中数据-1，缓存中标识状态删除，count值-1
         */
        Boolean result = this.removeComment(id, userId, CommentType.LOVE);
        if(!result){
            return false;
        }

        //操作缓存
        //新增喜欢的数量
        String publishKey = COMMENT_REDIS_KEY_PREFIX + id;
        String hashKey = CommentType.LOVE.toString();
        this.redisTemplate.opsForHash().increment(publishKey,hashKey,-1);

        //修改用户是否喜欢的状态
        String userLoveHashKey = COMMENT_USER_LOVE_REDIS_KEY_PREFIX + userId;
        //"1"是一个标识符，是1即标记为喜欢的状态，无或者其他就表示取消喜欢的状态,所以取消直接干掉它就完事了
        this.redisTemplate.opsForHash().delete(publishKey,userLoveHashKey);
        return true;
    }

    /**
     * 查询喜欢数量
     * 在用户喜欢和取消喜欢的时候，我们都将其对对应的redis缓存状态进行
     * 了改变，所以再查询数量的时候都首先走缓存查询，出现了redis宕机的情况
     * 我们再去数据库进行查询，然后再次将数据写入redis缓存中
     * @param id
     * @return
     */
    @Override
    public Long queryLoveCount(String id) {
        String publishKey = COMMENT_REDIS_KEY_PREFIX + id;
        String hashKey = CommentType.LOVE.toString();
        Object data = this.redisTemplate.opsForHash().get(publishKey, hashKey);
        if (ObjectUtil.isNotEmpty(data)) {
            //从redis缓存中取出查询数量返回
            return Convert.toLong(data);
        }
        //redis缓存中取不到，只能去mongodb数据库取了
        Long count = this.queryCommentCount(id, CommentType.LOVE);
        if (count != 0) {
            /*
            查出数据了,正是因为redis缓存中没有数据才会去数据库中查，所以将
            数据再次写入redis缓存中，方便下次进来直接走缓存查询，减轻数据库压力
             */
            this.redisTemplate.opsForHash().put(publishKey, hashKey, Convert.toStr(count));
            return count;
        }
        return null;
    }

    /**
     * 判断用户是否已经处于喜欢的状态
     * @param userId
     * @param id
     * @return
     */
    @Override
    public Boolean queryUserIsLove(Long userId, String id){
        /*
        如何判断用户是否已经处于喜欢还是非喜欢状态呢？
        有一个状态标识值
         */
        String publishKey = COMMENT_REDIS_KEY_PREFIX + id;
        String userLoveHashKey = COMMENT_USER_LOVE_REDIS_KEY_PREFIX + userId;
        Object data = this.redisTemplate.opsForHash().get(publishKey, userLoveHashKey);
        if(ObjectUtil.isNotEmpty(data)){
            //data中的数据是否为“1”，是返回true,不是返回false
            return StrUtil.equals(Convert.toStr(data),"1");
        }

        /*
        如果redis缓存发生了宕机(data == null)就一定是客户取消了喜欢的状态了吗？所以需要我们去数据库
        再次查询确保数据无误
         */
        Query query = Query.query(Criteria.where("userId").is(userId)
                .and("publishId").is(new ObjectId(id))
                .and("commentType").is(CommentType.LOVE.getType()));
        long count = this.mongoTemplate.count(query, Comment.class);
        if(count == 0){
            return false;
        }
        //由于redis缓存中查询不出数据，所以才需要查询数据库，所以我们需要再次将数据写入到缓存中
        this.redisTemplate.opsForHash().put(publishKey,userLoveHashKey,"1");
        return true;
    }

    /**
     * 查询评论
     * @param id
     * @param page
     * @param pageSize
     * @return
     */
    @Override
    public PageInfo<Comment> queryCommentList(String id, Integer page, Integer pageSize) {
        PageInfo pageInfo = new PageInfo();
        pageInfo.setPageNum(page);
        pageInfo.setPageSize(pageSize);

        Query query = Query.query(Criteria.where("publishId").is(new ObjectId(id))
                .and("commentType").is(CommentType.COMMENT.getType()))
                .with(PageRequest.of(page - 1,pageSize));
        List<Comment> commentList = this.mongoTemplate.find(query, Comment.class);
        if(CollUtil.isEmpty(commentList)){
            return pageInfo;
        }
        pageInfo.setRecords(commentList);
        return pageInfo;
    }

    /**
     * 查询评论数量
     * @param id
     * @return
     */
    @Override
    public Integer queryCommentCount(String id) {
        Query query = Query.query(Criteria.where("publishId").is(new ObjectId(id))
                .and("commentType").is(CommentType.COMMENT.getType()));
        long count = this.mongoTemplate.count(query, Comment.class);
        return Convert.toInt(count);
    }

    /**
     * 发表评论
     * @param userId
     * @param id
     * @param content
     * @return
     */
    @Override
    public Boolean saveComment(Long userId, String id, String content) {
        return this.saveComment(userId, id, CommentType.COMMENT, content);
    }

    /**
     * 查询消息点赞列表
     * @param id
     * @param page
     * @param pageSize
     * @return
     */
    @Override
    public PageInfo<Comment> queryLikeCommentListByUser(Long id, Integer page, Integer pageSize) {
        return this.queryCommonCommentListByUser(id,page,pageSize,CommentType.LIKE);
    }

    /**
     * 查询喜欢点赞列表
     * @param id
     * @param page
     * @param pageSize
     * @return
     */
    @Override
    public PageInfo<Comment> queryLoveCommentListByUser(Long id, Integer page, Integer pageSize) {
        return this.queryCommonCommentListByUser(id,page,pageSize,CommentType.LOVE);
    }

    /**
     * 查询评论点赞列表
     * @param id
     * @param page
     * @param pageSize
     * @return
     */
    @Override
    public PageInfo<Comment> queryCommentListByUser(Long id, Integer page, Integer pageSize) {
        return this.queryCommonCommentListByUser(id,page,pageSize,CommentType.COMMENT);
    }

    private PageInfo<Comment> queryCommonCommentListByUser(Long id, Integer page, Integer pageSize,CommentType commentType) {
        PageInfo<Comment> pageInfo = new PageInfo<>();
        pageInfo.setPageNum(page);
        pageInfo.setPageSize(pageSize);
        //关键的逻辑在于是谁点赞了我，这个我代表发布动态，评论，小视频的那个人
        Query query = Query.query(Criteria.where("publishUserId").is(id).and("commentType").is(commentType.getType()))
                .with(PageRequest.of(page-1,pageSize));
        List<Comment> commentList = this.mongoTemplate.find(query, Comment.class);
        if(CollUtil.isEmpty(commentList)){
            return pageInfo;
        }
        pageInfo.setRecords(commentList);
        return pageInfo;
    }

    /**
     * 查询用户所有的状态
     * @param page
     * @param pageSize
     * @param userId  指定用户id
     * @return
     */
    @Override
    public PageInfo<Publish> queryAlbumList(Integer page, Integer pageSize, Long userId) {
        PageInfo pageInfo = new PageInfo();
        pageInfo.setPageNum(page);
        pageInfo.setPageSize(pageSize);

        Query query = new Query().with(PageRequest.of(page-1,pageSize)).with(Sort.by(Sort.Order.desc("created")));
        //按照时间倒序的排序方法查找指定用户的指定相册表
        List<Album> albumList = this.mongoTemplate.find(query, Album.class, "quanzi_album_" + userId);
        if(CollUtil.isEmpty(albumList)){
            return pageInfo;
        }

        //获取相册表中所有的publishId
        List<Object> publishIds = CollUtil.getFieldValues(albumList, "publishId");
        Query query1 = Query.query(Criteria.where("id").in(publishIds)).with(Sort.by(Sort.Order.desc("created")));
        List<Publish> publishList = this.mongoTemplate.find(query1, Publish.class);
        if(CollUtil.isEmpty(publishList)){
            return pageInfo;
        }
        pageInfo.setRecords(publishList);
        return pageInfo;
    }

    /**
     * 评论列表翻页
     * @param sortProp
     * @param page
     * @param pageSize
     * @param sortOrder
     * @param messageID
     * @return
     */
    @Override
    public PageInfo<Comment> queryComment(String sortProp, Integer page, Integer pageSize, String sortOrder, String messageID) {
        PageInfo pageInfo = new PageInfo();
        pageInfo.setPageNum(page);
        pageInfo.setPageSize(pageSize);
        PageRequest pageRequest;
        if (StringUtils.equals(sortOrder, "descending")) {
            pageRequest = PageRequest.of(page - 1, pageSize, Sort.by(Sort.Order.desc(sortProp)));
        } else {
            pageRequest = PageRequest.of(page - 1, pageSize, Sort.by(Sort.Order.asc(sortProp)));
        }

        Messages messages = messagesApi.queryMessages(messageID.toString());

        Query query = Query.query(Criteria.where("commentType").is(1).and("publishId").is(new ObjectId(messages.getMId().toHexString())));
        List<Comment> comments = this.mongoTemplate.find(query, Comment.class);
        if(CollUtil.isEmpty(comments)){
            return pageInfo;
        }
        pageInfo.setRecords(comments);
        return pageInfo;
    }

    @Override
    public List<Publish> queryPublishList(List<String> publishIds, Integer page, Integer pageSize) {
        List<ObjectId> publishIdList = new ArrayList<>();
        for (String id : publishIds) {
            //将String类型转化为ObjectId类型
            publishIdList.add(new ObjectId(id));
        }
        List<Publish> publishList = this.mongoTemplate.find(Query.query(Criteria.where("id").in(publishIdList)), Publish.class);
        if(CollUtil.isEmpty(publishList)){
            return ListUtil.empty();
        }
        return publishList;
    }

    private Boolean savePublishToMessages(Publish publish){
        Long loveCount = this.queryLoveCount(publish.getId().toHexString());
        Long likeCount = this.queryLikeCount(publish.getId().toHexString());
        Integer commentCount = this.queryCommentCount(publish.getId().toHexString());
        //发布动态的同时给Messages表中写入用户发布的数据
        return this.messagesApi.saveMessages(publish.getUserId(), publish.getId()
                , Convert.toInt(loveCount), Convert.toInt(likeCount), Convert.toInt(commentCount), publish.getCreated());
    }
}
